package com.lhd.qd.common.aspect;

import com.lhd.qd.common.util.CommonUtils;
import com.lhd.qd.common.util.UserUtils;
import com.lhd.qd.module.system.user.service.UserOperateLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 操作日志
 */
@Aspect
@Component
public class OperateLogAspect {

    @Autowired
    private UserOperateLogService userOperateLogService;

    @Pointcut("@annotation(com.lhd.qd.common.annotation.OperateLog)")
    public void pointcut() {}

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {

        Object obj = pjp.proceed();

        setLog(pjp, obj);

        return obj;
    }

    private void setLog(ProceedingJoinPoint pjp, Object obj) {

        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        userOperateLogService.saveUserOperateLog(
                UserUtils.getId(),
                getOperateDesc(pjp),
                request.getMethod(),
                request.getRequestURI(),
                CommonUtils.getRequestLongIp(request),
                pjp.getArgs(),
                obj
        );
    }

    private String getOperateDesc(ProceedingJoinPoint pjp) {
        Class<?> targetClass = pjp.getTarget().getClass();
        Api api = targetClass.getAnnotation(Api.class);

        MethodSignature methodSignature = ((MethodSignature) pjp.getSignature());
        ApiOperation apiOperation = null;
        try {
            apiOperation = targetClass
                    .getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes()).getAnnotation(ApiOperation.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        String classDesc = api != null && api.tags().length > 0 ? api.tags()[0] : "";
        String methodDesc = apiOperation != null ? apiOperation.value() : "";
        return String.format("%s-%s", classDesc, methodDesc);
    }
}
